﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Configuration;
using AffinityORMLibrary.DataTypes;
using AffinityORMLibrary.DataLayer.Assembler;
using AffinityORMLibrary.DataLayer.Action;
using System.Data;

namespace AffinityORMLibrary.DataLayer.Factory
{
    abstract class FactoryBase<Domain>
    {
        private System.Data.Common.DbProviderFactory _dbFactory;
        ConnectionStringSettings _connStr;

        public FactoryBase(ConnectionStringSettings connectionString)
        {
            _connStr = connectionString;
            _dbFactory = DbProviderFactories.GetFactory(_connStr.ProviderName);
        }

        public List<Domain> Find(DataBase selection, IAssembler<Domain> assembler, ISelectionAction action)
        {
            List<Domain> result = new List<Domain>();

            DbConnection connection = OpenConnection();
            using (DbCommand command = action.Select(_dbFactory, selection))
            {
                command.Connection = connection;
                using (IDataReader rdr = command.ExecuteReader())
                {
                    while (rdr.Read())
                    {
                        result.Add(assembler.Construct(rdr));
                    }
                }
            }
            CloseConnection(connection);
            return result;
        }

        private DbConnection OpenConnection()
        {
            DbConnection connection = _dbFactory.CreateConnection();
            connection.ConnectionString = _connStr.ConnectionString;
            connection.Open();
            return connection;
        }

        private void CloseConnection(DbConnection connection)
        {
            connection.Close();
        }
    }
}
